package fr.imag.ufrima.ctte.gui.editors;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.ImageIcon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTabbedPane;
import javax.swing.event.MouseInputAdapter;

import fr.imag.ufrima.ctte.ImagCTTE;
import fr.imag.ufrima.ctte.Task;
import fr.imag.ufrima.ctte.TaskDiagram;
import fr.imag.ufrima.ctte.enums.EditorModes;
import fr.imag.ufrima.ctte.events.TaskDiagramAdapter;
import fr.imag.ufrima.ctte.events.TaskDiagramEvent;
import fr.imag.ufrima.ctte.gui.toolbars.DiagramEditorInputsToolBar;
import fr.imag.ufrima.ctte.gui.toolbars.DiagramEditorOrganizeToolBar;

public class TaskDiagramDesignPanel extends javax.swing.JPanel {
	private ImagCTTE imagCTTE;
	private TaskDiagramEditor editor;
	private TaskDiagram taskDiagram;
	private Point startPoint;
	private Point hintPoint;
	private JTabbedPane parentTabbedPane;		
	private Image image;
	final static float dash1[] = {10.0f};
    final static BasicStroke dashed = new BasicStroke(1.0f, 
                                          BasicStroke.CAP_BUTT, 
                                          BasicStroke.JOIN_MITER, 
                                          10.0f, dash1, 0.0f);
    private JPopupMenu taskPopup;
    private JPopupMenu operatorPopup;
    
	/**
	 * Contructor
	 * @param imagCTTE
	 */
    public TaskDiagramDesignPanel(ImagCTTE imagCTTE, TaskDiagram taskDiagram, TaskDiagramEditor editor){
		this.imagCTTE = imagCTTE;
		this.taskDiagram = taskDiagram;
		this.editor = editor;							
		
		InitComponents();
		
		// task diagram events
		final TaskDiagramDesignPanel tde = this; // just for test
		taskDiagram.addTaskDiagramListener(new TaskDiagramAdapter(){
			public void titleChanged(TaskDiagramEvent event) {							
				for (int i=0; i<getEditor().getComponentCount(); i++){
					if (getEditor().getComponent(i) == tde){						
						getEditor().setTitleAt(i, event.getTaskDiagram().getTitle());
					}
				}				
			}		
			public void dimensionChanged(TaskDiagramEvent event) {			
				super.dimensionChanged(event);
				int w = event.getTaskDiagram().getWidth();
				int h = event.getTaskDiagram().getHeight();
				drawingPanel.setPreferredSize(new Dimension(w,h));
				drawingPanel.setSize(new Dimension(w,h));
				image = createImage(getTaskDiagram().getWidth(), getTaskDiagram().getHeight()); //Width and Height are fields in class
				TaskDiagramDesignPanel.this.repaint();
			}	
			/*public void selectionChanged(TaskDiagramEvent event) {						
				TaskDiagramDesignPanel.this.repaint();		
			}*/						
			public void selectedTaskChanged(TaskDiagramEvent event) {
				TaskDiagramDesignPanel.this.repaint();
			}			
			public void selectedOperatorChanged(TaskDiagramEvent event) {
				TaskDiagramDesignPanel.this.repaint();
			}
			public void taskAdded(TaskDiagramEvent event) {			
				TaskDiagramDesignPanel.this.repaint();
			}			
			public void taskPropertiesChanged(TaskDiagramEvent event) {
				TaskDiagramDesignPanel.this.repaint();
			}						
			public void operatorPropertiesChanged(TaskDiagramEvent event) {
				TaskDiagramDesignPanel.this.repaint();
			}
			public void interLevelDistanceChanged(TaskDiagramEvent event) {				
				TaskDiagramDesignPanel.this.repaint();
			}
		});		
		
		// Mouse listener
		class Listner extends MouseInputAdapter{
			Point point1 = null;
			Point point2 = null;
			boolean dragging = false;
			
			public void mouseMoved(MouseEvent e) {		
				hintPoint = e.getPoint();
				getTaskDiagram().hintObject(e.getPoint());
				TaskDiagramDesignPanel.this.repaint();
			}
			public void mouseDragged(MouseEvent e) {	
				if (point1 != null){
					if (dragging == true){
						point2 = e.getPoint();						
						
						int newXValue = jScrollPane.getHorizontalScrollBar().getValue() + (point2.x - point1.x); 
						if (newXValue >= jScrollPane.getHorizontalScrollBar().getMinimum()
								&& newXValue <= jScrollPane.getHorizontalScrollBar().getMaximum()) {
							jScrollPane.getHorizontalScrollBar().setValue(newXValue);
						}
						
						int newYValue = jScrollPane.getVerticalScrollBar().getValue() + (point2.y - point1.y); 
						if (newYValue >= jScrollPane.getVerticalScrollBar().getMinimum()
								&& newYValue <= jScrollPane.getVerticalScrollBar().getMaximum()) {
							jScrollPane.getVerticalScrollBar().setValue(newYValue);
						}
						point1 = point2;
					}
				} 
			}
			public void mousePressed(MouseEvent e) {				
				switch(e.getButton()){
					case MouseEvent.BUTTON1: {
						point1 = e.getPoint();
						if (getTaskDiagram().getEditorModes() == EditorModes.NONE){
							getTaskDiagram().selectObject(e.getPoint());
						} else if (getTaskDiagram().getEditorModes() == EditorModes.INSERING_TASK){													
							getTaskDiagram().addTask();
							
						} else if (getTaskDiagram().getEditorModes() == EditorModes.INSERING_OPERATOR){
							getTaskDiagram().AddOperator();
							
						}							
						dragging = true;
						TaskDiagramDesignPanel.this.repaint();
						
					}break;
					case MouseEvent.BUTTON3: {
						
						getTaskDiagram().selectObject(e.getPoint());						
						if (getTaskDiagram().getSelectedTask() != null){
							makeTaskPopupMenu();
							getTaskPopup().show(TaskDiagramDesignPanel.this.getParent(), e.getX() + 30, e.getY());
							
						} else if (getTaskDiagram().getSelectedOperator() != null){
							makeOperatorPopupMenu();
							getOperatorPopup().show(TaskDiagramDesignPanel.this.getParent(), e.getX() + 30, e.getY());
						}
					}break;
				}
			}
			public void mouseReleased(MouseEvent e) {
				
				point1 = null;
				point2 = null;
				dragging = false;
			}		
		}
		Listner listner = new Listner();
		drawingPanel.addMouseListener(listner);
		drawingPanel.addMouseMotionListener(listner);			
		
		
	}
    private void makeTaskPopupMenu(){
    	taskDiagram = imagCTTE.getCurrentTaskDiagram();
    	taskPopup = new JPopupMenu();
    	final JCheckBoxMenuItem cbmi1 = new JCheckBoxMenuItem("Iteratif", 
				taskDiagram.getSelectedTask().isIteratif());
		cbmi1.addActionListener(new ActionListener(){			
			public void actionPerformed(ActionEvent event) {
				JCheckBoxMenuItem o = (JCheckBoxMenuItem)event.getSource();
				taskDiagram.getSelectedTask().setIteratif(o.isSelected());
			}
		});
		taskPopup.add(cbmi1);
		final JCheckBoxMenuItem cbmi2 = new JCheckBoxMenuItem("Optional", 
				taskDiagram.getSelectedTask().isOptional());
		cbmi2.addActionListener(new ActionListener(){			
			public void actionPerformed(ActionEvent event) {
				JCheckBoxMenuItem o = (JCheckBoxMenuItem)event.getSource();
				taskDiagram.getSelectedTask().setOptional(o.isSelected());
			}
		});
		taskPopup.add(cbmi2);
    }
    private void makeOperatorPopupMenu(){
    	taskDiagram = imagCTTE.getCurrentTaskDiagram();
    	operatorPopup = new JPopupMenu();
		final JCheckBoxMenuItem cbmi1 = new JCheckBoxMenuItem("Choice", new ImageIcon("images\\choice.gif"), 
				taskDiagram.getSelectedOperator().getTypeAsString().equals("Choice"));
		cbmi1.addActionListener(new ActionListener(){			
			public void actionPerformed(ActionEvent arg0) {
				taskDiagram.getSelectedOperator().setType(cbmi1.getText());
			}
		});
		operatorPopup.add(cbmi1);
		final JCheckBoxMenuItem cbmi2 = new JCheckBoxMenuItem("Order Independency", new ImageIcon("images\\order.gif"), 
				taskDiagram.getSelectedOperator().getTypeAsString().equals("Order Independency"));
		cbmi2.addActionListener(new ActionListener(){			
			public void actionPerformed(ActionEvent arg0) {
				taskDiagram.getSelectedOperator().setType(cbmi2.getText());
			}
		});

		operatorPopup.add(cbmi2);
		final JCheckBoxMenuItem cbmi3 = new JCheckBoxMenuItem("Concurrent", new ImageIcon("images\\interleave.gif"), 
				taskDiagram.getSelectedOperator().getTypeAsString().equals("Concurrent"));
		cbmi3.addActionListener(new ActionListener(){			
			public void actionPerformed(ActionEvent arg0) {
				taskDiagram.getSelectedOperator().setType(cbmi3.getText());
			}
		});

		operatorPopup.add(cbmi3);
		final JCheckBoxMenuItem cbmi4 = new JCheckBoxMenuItem("Concurrent with info exchange", new ImageIcon("images\\sincro.gif"), 
				taskDiagram.getSelectedOperator().getTypeAsString().equals("Concurrent with info exchange"));
		cbmi4.addActionListener(new ActionListener(){			
			public void actionPerformed(ActionEvent arg0) {
				taskDiagram.getSelectedOperator().setType(cbmi4.getText());
			}
		});

		operatorPopup.add(cbmi4);
		final JCheckBoxMenuItem cbmi5 = new JCheckBoxMenuItem("CTT Disabling", new ImageIcon("images\\disabling.gif"), 
				taskDiagram.getSelectedOperator().getTypeAsString().equals("CTT Disabling"));
		cbmi5.addActionListener(new ActionListener(){			
			public void actionPerformed(ActionEvent arg0) {
				taskDiagram.getSelectedOperator().setType(cbmi5.getText());
			}
		});
		operatorPopup.add(cbmi5);
		final JCheckBoxMenuItem cbmi6 = new JCheckBoxMenuItem("Suspend/Resume", new ImageIcon("images\\suspend.gif"), 
				taskDiagram.getSelectedOperator().getTypeAsString().equals("Suspend/Resume"));
		cbmi6.addActionListener(new ActionListener(){			
			public void actionPerformed(ActionEvent arg0) {
				taskDiagram.getSelectedOperator().setType(cbmi6.getText());
			}
		});
		operatorPopup.add(cbmi6);
		final JCheckBoxMenuItem cbmi7 = new JCheckBoxMenuItem("Enabling", new ImageIcon("images\\enabling.gif"), 
				taskDiagram.getSelectedOperator().getTypeAsString().equals("Enabling"));
		cbmi7.addActionListener(new ActionListener(){			
			public void actionPerformed(ActionEvent arg0) {
				taskDiagram.getSelectedOperator().setType(cbmi7.getText());
			}
		});
		operatorPopup.add(cbmi7);
		final JCheckBoxMenuItem cbmi8 = new JCheckBoxMenuItem("Enabling with info exchange", new ImageIcon("images\\enablinginfo.gif"), 
				taskDiagram.getSelectedOperator().getTypeAsString().equals("Enabling with info exchange"));
		cbmi8.addActionListener(new ActionListener(){			
			public void actionPerformed(ActionEvent arg0) {
				taskDiagram.getSelectedOperator().setType(cbmi8.getText());
			}
		});
		operatorPopup.add(cbmi8);
    }
	/**
	 * Initialize componenets
	 */
	protected void InitComponents(){
		this.setLayout(new BorderLayout());
		// toolbars
        diagramEditorInputsToolBar = new DiagramEditorInputsToolBar(imagCTTE);        
        diagramEditorOrganizeToolBar = new DiagramEditorOrganizeToolBar(imagCTTE);
        
        jScrollPane = new javax.swing.JScrollPane();
        
        // Overide the paint method of the drawing panel        
        drawingPanel = new javax.swing.JPanel() {        	
        	protected void paintComponent(Graphics g) {
	        	super.paintComponent(g);
	        	
	        	int width  = taskDiagram.getWidth();
	        	int height = taskDiagram.getHeight();
	        	
	    		if (image == null) {
	                image = createImage(taskDiagram.getWidth(), taskDiagram.getHeight()); //Width and Height are fields in class
	    		}
	            Graphics2D g2d = (Graphics2D)image.getGraphics();
	            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
	     
	            // draw the diagram in the image // to accelerate the drawing
	            // draw the area
	            g2d.setColor(Color.WHITE);
	    		g2d.fillRect(0, 0, width, height);
	    		g2d.setStroke(dashed);
	    		g2d.setColor(Color.ORANGE);
	    		g2d.drawLine(width-1, 0, width-1, height);
	    		g2d.drawLine(0, height-1, width, height-1);
	    		
	    		g2d.setStroke(new BasicStroke(0.5f));	    		
	    		
	    		g2d.setColor(Color.BLACK);			    			    		
	    		// Draw the tasks
	    		taskDiagram.repaint(g2d);
				if (taskDiagram.getHintedTask() != null){
					taskDiagram.getHintedTask().drawHinted(g2d, hintPoint);
				}
				if (taskDiagram.getSelectedTask() != null){
					taskDiagram.getSelectedTask().drawSelected(g2d);
				}
				if (taskDiagram.getHintedOperatorStartTask() != null){					
					taskDiagram.getHintedOperatorStartTask().drawHintedOperator(g2d);
				}
				if (taskDiagram.getSelectedOperator() != null){
					taskDiagram.getSelectedOperator().drawSelected(g2d);
				}
				// Draw the buffered image
	            g.drawImage(image, 0,0,width,height, null);
	            
        	}
        };
                
        jScrollPane.setViewportView(drawingPanel);
        drawingPanel.setSize(taskDiagram.getWidth(), taskDiagram.getHeight());
        drawingPanel.setPreferredSize(new Dimension(taskDiagram.getWidth(), taskDiagram.getHeight()));
        
        diagramEditorInputsToolBar.add(diagramEditorOrganizeToolBar);
        this.add(diagramEditorInputsToolBar , java.awt.BorderLayout.PAGE_START);
               
        // drawing panel
        drawingPanel.setBackground(Color.WHITE);
        this.add(jScrollPane, java.awt.BorderLayout.CENTER);
	}
	public TaskDiagram getTaskDiagram() {
		return taskDiagram;
	}
	public void setTaskDiagram(TaskDiagram taskDiagram) {
		this.taskDiagram = taskDiagram;
	}
	public TaskDiagramEditor getEditor() {
		return editor;
	}
	public void setEditor(TaskDiagramEditor editor) {
		this.editor = editor;
	}
	/**
	 * Components
	 */
	private DiagramEditorInputsToolBar diagramEditorInputsToolBar;
    private DiagramEditorOrganizeToolBar diagramEditorOrganizeToolBar;            
    private javax.swing.JPanel drawingPanel;    
    private javax.swing.JScrollPane jScrollPane;
	public JPopupMenu getTaskPopup() {
		return taskPopup;
	}
	public void setTaskPopup(JPopupMenu taskPopup) {
		this.taskPopup = taskPopup;
	}
	public JPopupMenu getOperatorPopup() {
		return operatorPopup;
	}
	public void setOperatorPopup(JPopupMenu operatorPopup) {
		this.operatorPopup = operatorPopup;
	}


}
